package com.redhipps.hips.client.command;

import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.redhipps.hips.client.HipsApp;
import com.redhipps.hips.client.io.IOService;
import com.redhipps.hips.client.io.IOServiceFactory;
import com.redhipps.hips.client.io.RequestBuilderFactory;
import com.redhipps.hips.client.model.Context;

/**
 * Base class for commands that rely on a {@link Context} in order to operate.
 * Exposing an {@code execute} method with a {@link Context} as argument makes
 * it easier to do dependency injection.
 * 
 * @author yuhong
 */
public abstract class HipsCommand<ResultType> implements Command {

  /**
   * @see Command#execute()
   */
  public final void execute() {
    execute(new AsyncCallback<ResultType>() {
      public void onFailure(Throwable caught) {
        // no-op
      }
      public void onSuccess(ResultType result) {
        // no-op
      }
    });
  }

  protected Context context() {
    return Context.rootContext();
  }

  protected IOServiceFactory ioServiceFactory() {
    return HipsApp.ioServiceFactory();
  }

  protected IOService ioService() {
    return ioServiceFactory().ioService();
  }

  protected RequestBuilderFactory requestBuilderFactory() {
    return HipsApp.requestBuilderFactory();
  }

  /**
   * Executes command under given context and invokes callback when complete.
   * 
   * @param context Context for command.
   * @param callback Callback to invoke when done.
   *     TODO The argument of this callback is the completed model operation for
   *     the command. Having a single model in the result makes sense for some
   *     commands such as the Create* commands. But this doesn't really jive with
   *     the list commands. Find a more elegant way to deal.
   */
  abstract public void execute(AsyncCallback<ResultType> callback);

}
